/*	--- 使用Filter --- 


Stream.filter() 是 Stream 的另一个【常用转换方法】。

所谓【filter()操作】，就是对【一个Stream的所有元素】一一进行【测试】，
不满足条件的就被“滤掉”了，剩下的满足条件的元素就构成了一个新的Stream。


例如，我们对1，2，3，4，5这个Stream调用【filter()】，传入的【测试函数f(x) = x % 2 != 0】用来判断【元素是否是奇数】，这样就【过滤掉偶数】，【只剩下】奇数，因此我们得到了【另一个序列1，3，5】：


		 f(x) = x % 2 != 0

	                  │
	                  │
	  ┌───┬───┬───┬───┼───┬───┬───┬───┐
	  │   │   │   │   │   │   │   │   │
	  ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼

	[ 1   2   3   4   5   6   7   8   9 ]

	  │   X   │   X   │   X   │   X   │  .filter(x -> x % 2 != 0)
	  │       │       │       │       │
	  ▼       ▼       ▼       ▼       ▼

	[ 1       3       5       7       9 ]



用IntStream写出上述逻辑，代码如下：*/
import java.util.stream.IntStream;

public class Main {
	public static void main(String[] args) {
		IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
				 .filter(n -> n %2 != 0)
				 .forEach(System.out::println);
	}
}


/*
从结果可知，经过filter()后生成的Stream元素可能变少。

【filter()方法接收的对象】是【Predicate接口对象】，它定义了一个【test()方法】，负责【判断元素是否符合条件】：*/
@FunctionalInterface
public interface Predicate<T> {
	// 判断【元素t】是否【符合条件】
	boolean test(T t);
}


/*
filter()除了常用于数值外，也可应用于任何Java对象。

例如，从一组【给定的LocalDate】中过滤掉【工作日】，以便得到【休息日】：*/
import java.time.*;
import java.util.function.*;
import java.util.stream.*;

public class Main {
	public static void main(String[] args) {
		Stream.generate(new LocalDateSupplier())
			  .limit(31)
			  .filter(ldt -> ldt.getDayOfWeek() == DayOfWeek.SATURDAY || ldt.getDayOfWeek() == DayOfWeek.SUNDAY)
			  .forEach(System.out::println);
	}
}

class LocalDateSupplier implements Supplier<LocalDate> {
	LocalDate start = LocalDate.of(2020, 1, 1);

	int n = -1;

	public LocalDate get() {
		n++;
		return start.plusDays(n);
	}

}



/*--------------------------------------------------------

#	练习

请使用filter()过滤出成绩及格的同学，并打印出名字。*/
class Person {
	String name;
	int score;

	Person(String name, int score) {
		this.name = name;
		this.score = score;
	}
}

public class Main {
	public static void main(String[] args) {
		List<Person> persons = List.of(new Person("小明", 99), new Person("小红", 44), new Person("小白", 60));

		// 使用 .filter() 过滤出及格的同学, 然后打印出名字
		persons.stream()
			   .filter(p -> p.score >= 60)
			   .map(s -> s.name)
			   .forEach(System.out::println);
	}
}


/*------------------
方法2: */
public class FilterProblem {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("小明", 88),
                new Person("小黑", 62),
                new Person("小白", 45),
                new Person("小黄", 78),
                new Person("小红", 99),
                new Person("小林", 58));
        
        persons.stream()
                .filter(p -> p.score >= 60)
                .forEach(p -> System.out.println(p.name));
    }
}

class Person {
    String name;
    int score;

    Person(String name, int score) {
        this.name = name;
        this.score = score;
    }
}

/*============================================================


#	----- 使用Filter の 小结 ----- 


1. 使用filter()方法可以对一个Stream的每个元素进行测试，通过测试的元素被过滤后生成一个新的Stream。



*/





